/*
 *  linux/fs/stat.c
 *
 *  (C) 1991  Linus Torvalds
 */

#include <errno.h>          // 错误号头文件 包含系统中各种出错号 （Linus 从MINIX 中引进的）
#include <sys/stat.h>       // 文件状态头文件 含有文件或文件系统状态结构 stat 和 常量

#include <linux/fs.h>       // 文件系统头文件 定义文件表结构（file buffer_head m_indoe 等）
#include <linux/sched.h>    // 调度程序头文件 定义任务结构 task_struct 初始任务0 的数据
#include <linux/kernel.h>   // 内核头文件 含有一些内核常用函数的原形定义
#include <asm/segment.h>    // 段操作头文件 定义了有关段寄存器操作的嵌入式汇编函数
//  复制文件状态信息    // 参数inode是文件对应的i节点 statbuf是stat文件状态结构指针 用于存放取得的状态信息
static void cp_stat(struct m_inode * inode, struct stat * statbuf)
{
	struct stat tmp;
	int i;
    // 首先验证（或分配）存放数据的内存空间 然后临时复制相应节点上的信息
	verify_area(statbuf,sizeof (* statbuf));
	tmp.st_dev = inode->i_dev;      // 文件所在的设备号
	tmp.st_ino = inode->i_num;      // 文件i节点号
	tmp.st_mode = inode->i_mode;    // 文件属性
	tmp.st_nlink = inode->i_nlinks; // 文件的连接数
	tmp.st_uid = inode->i_uid;      // 文件的用户id
	tmp.st_gid = inode->i_gid;      // 文件的组id
	tmp.st_rdev = inode->i_zone[0]; // 设备号（如果文件是特殊的字符文件或块文件）
	tmp.st_size = inode->i_size;    // 文件大小（字节数）（如果文件时常规文件）
	tmp.st_atime = inode->i_atime;  // 最后的访问时间
	tmp.st_mtime = inode->i_mtime;  // 最后的修改时间
	tmp.st_ctime = inode->i_ctime;  // 最后节点修改时间
	for (i=0 ; i<sizeof (tmp) ; i++)    // 最后将这些状态信息复制到用户缓冲区中
		put_fs_byte(((char *) &tmp)[i],&((char *) statbuf)[i]);
}
// 文件状态系统调用函数-根据文件名获取文件状态信息 返回0 若出错则返回出错码 参数 filename-指定的文件名 statbuf-是存放状态信息的缓冲区指针
int sys_stat(char * filename, struct stat * statbuf)
{
	struct m_inode * inode;
    // 首先根据文件名找出对应的i节点 若出错则返回错误码
	if (!(inode=namei(filename)))
		return -ENOENT;
	cp_stat(inode,statbuf); // 将i节点上文件状态信息复制到用户缓冲区中，并释放该i节点
	iput(inode);
	return 0;
}
// 文件状态系统调用-根据文件句柄获取文件状态信息 返回0，若出错则返回出错码 参数fd是指定文件的句柄（描述符） statbuf是存放状态信息的缓冲区指针
int sys_fstat(unsigned int fd, struct stat * statbuf)
{
	struct file * f;
	struct m_inode * inode;
    // 如果文件句柄值大于一个程序最多打开文件数NR_OPEN，或者该句柄的文件结构指针为空 或者对应文件结构的i节点字段为空 则出错 返回出错码并退出
	if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode))
		return -EBADF;
	cp_stat(inode,statbuf); // 将i节点上的文件状态信息复制到用户缓冲区中
	return 0;
}
